#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/system_properties.h>
#include <android/log.h>

#define DBGPRINT(...) __android_log_print(ANDROID_LOG_DEBUG, "sd_otg", __VA_ARGS__)

#define PROPERTY_VALUE_MAX 92
static char custom_id[PROPERTY_VALUE_MAX];

#define DELETE_USB_LINK 0

static char sdk_version[1024] = { 0 };

static char board_platform[PROPERTY_VALUE_MAX] = { 0 };
static char g_otg_path[1024] = { 0 };
static char g_find_otg_path = 0;

static char g_usb_udc_path[1024] = { 0 };
static char g_find_udc_path = 0;
int platfrom_usb_switch_device();
void platfrom_usb_switch_host();

static void delete_usb_link() {
#if DELETE_USB_LINK
	DBGPRINT("%s:%d start\n", __func__, __LINE__);
	if(access("/config/usb_gadget/g1/configs/b.1/f1",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f1");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f2",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f2");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f3",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f3");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f4",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f4");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f5",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f5");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f6",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f6");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f7",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f7");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f8",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f8");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f9",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f9");
	}
	if(access("/config/usb_gadget/g1/configs/b.1/f10",F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f10");
	}
	DBGPRINT("%s:%d end\n", __func__, __LINE__);
#else
	DBGPRINT("%s:%d start\n", __func__, __LINE__);
	if (access("/config/usb_gadget/g1/configs/b.1/f1", F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f1");
	}
	if (access("/config/usb_gadget/g1/configs/b.1/f2", F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f2");
	}
	if (access("/config/usb_gadget/g1/configs/b.1/f3", F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f3");
	}
	if (access("/config/usb_gadget/g1/configs/b.1/f4", F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f4");
	}
	if (access("/config/usb_gadget/g1/configs/b.1/f5", F_OK) == 0) {
		system("rm /config/usb_gadget/g1/configs/b.1/f5");
	}

#endif
}

static int check_usb_usb_gadget_UDC() {
	char value[256];
	int fd;
	g_find_udc_path = 0;
	memset(g_usb_udc_path, 0, 1024);
	if ((fd = open("/config/usb_gadget/g1/UDC", O_RDONLY)) < 0) {
		DBGPRINT(
				"open(/config/usb_gadget/g1/UDC) failed: %s (%d)\n", strerror(errno), errno);
		return 0;
	}

	memset(g_usb_udc_path, 0, sizeof(g_usb_udc_path));
	read(fd, &g_usb_udc_path, sizeof(g_usb_udc_path));
	char *p = strchr(g_usb_udc_path, '\n');
	if (p != NULL) {
		*p = '\0';
	}
	DBGPRINT(
			"/config/usb_gadget/g1/UDC:g_usb_udc_path:%s,len=%d\n", g_usb_udc_path, strlen(g_usb_udc_path));
	if (strlen(g_usb_udc_path) > 1) {
		g_find_udc_path = 1;
	} else {
		if (strlen(g_usb_udc_path) <= 1) {
			__system_property_get("sys.usb.controller", g_usb_udc_path);
			DBGPRINT(
					"sys.usb.controller:g_usb_udc_path:%s,len=%d\n", g_usb_udc_path, strlen(g_usb_udc_path));
			g_find_udc_path = 1;
		}
	}
	close(fd);
	return 1;
}

static int check_platform_otg_path() {

	char otg_path[1024] = { 0 };
	__system_property_get("ro.board.platform", board_platform);
	DBGPRINT("board_platform:%s \n", board_platform);

	g_find_otg_path = 0;
	memset(g_otg_path, 0, 1024);
	//__system_property_set("sys.suding.reverse.custom","hengchangtong");
	__system_property_get("sys.suding.reverse.custom", custom_id);
	if (strcmp(custom_id, "hct_reverse") == 0) {
		//hct
		strcpy(otg_path, "/sys/bus/platform/drivers/usb20_otg/force_usb_mode");
		if (access(otg_path, F_OK) == 0) {
			strcpy(g_otg_path, otg_path);
			goto find;
		}
	} else if (strcmp(custom_id, "sd_reverse") == 0) {
		//rk3399
		///sys/devices/platform/ff770000.syscon/ff770000.syscon:usb2-phy@e450/otg_mode
		//sd
		strcpy(otg_path,
				"/sys/devices/platform/ff770000.syscon/ff770000.syscon:usb2-phy@e450/otg_mode");
		if (access(otg_path, F_OK) == 0) {
			strcpy(g_otg_path, otg_path);
			goto find;
		}
	} else if (strcmp(custom_id, "sd_msm808") == 0) {
		///sys/devices/platform/soc/7000000.ssusb/mode
		//sd
		strcpy(otg_path, "/sys/devices/platform/soc/7000000.ssusb/mode");
		if (access(otg_path, F_OK) == 0) {
			strcpy(g_otg_path, otg_path);
			goto find;
		}
	}

	DBGPRINT("no find g_otg_path err!!!!!!\n");
	return 0;
	find: g_find_otg_path = 1;
	DBGPRINT("find g_otg_path:%s\n", g_otg_path);
	return 1;
}

static int platform_usb_apple_device() {

	int ret = 1;
	char path[1024] = { 0 };
	int result = 0;
	DBGPRINT("%s:%d\n", __func__, __LINE__);
	platfrom_usb_switch_device();

	if (strcmp(custom_id, "hct_reverse") == 0) {
		__system_property_set("sys.usb.configfs", "2");
		DBGPRINT("%s:%d,sys.usb.configfs 2\n", __func__, __LINE__);
	}
	__system_property_set("sys.usb.ffs.ready", "0");

	delete_usb_link();
	DBGPRINT("%s:%d\n", __func__, __LINE__);
	system("mount -t configfs none /sys/kernel/config");
	if (access("/sys/kernel/config/usb_gadget/g1", F_OK)) {
		system("mkdir -p /sys/kernel/config/usb_gadget/g1");
	}
	system("echo \"0x05ac\"  > /sys/kernel/config/usb_gadget/g1/idVendor");
	system("echo \"0x12a8\"  > /sys/kernel/config/usb_gadget/g1/idProduct");
	system("echo \"0x1001\"  > /sys/kernel/config/usb_gadget/g1/bcdDevice");
	if (access("/sys/kernel/config/usb_gadget/g1/strings/0x409", F_OK)) {
		system("mkdir /sys/kernel/config/usb_gadget/g1/strings/0x409");
	}
	system(
			"echo \"6a001f5ae423f030c687441ff4dbcb7dbf3e8b26\"  > /sys/kernel/config/usb_gadget/g1/strings/0x409/serialnumber");
	system(
			"echo \"Apple Inc.\"  > /sys/kernel/config/usb_gadget/g1/strings/0x409/manufacturer");
	system(
			"echo \"iPhone\"  > /sys/kernel/config/usb_gadget/g1/strings/0x409/product");

	DBGPRINT("%s:%d\n", __func__, __LINE__);
	if (access("/sys/kernel/config/usb_gadget/g1/functions/ptp_sd.usb0",
			F_OK)) {
		system("mkdir /sys/kernel/config/usb_gadget/g1/functions/ptp_sd.usb0");
	}
	if (access("/sys/kernel/config/usb_gadget/g1/functions/audio_sd.usb0",
			F_OK)) {
		system(
				"mkdir /sys/kernel/config/usb_gadget/g1/functions/audio_sd.usb0");
	}
	if (access("/sys/kernel/config/usb_gadget/g1/functions/hid_sd.usb0",
			F_OK)) {
		system("mkdir /sys/kernel/config/usb_gadget/g1/functions/hid_sd.usb0");
	}
	if (access("/sys/kernel/config/usb_gadget/g1/functions/mux_sd.usb0",
			F_OK)) {
		system("mkdir /sys/kernel/config/usb_gadget/g1/functions/mux_sd.usb0");
	}
	if (access("/sys/kernel/config/usb_gadget/g1/functions/vsc_sd.usb0",
			F_OK)) {
		system("mkdir /sys/kernel/config/usb_gadget/g1/functions/vsc_sd.usb0");
	}

	DBGPRINT("%s:%d\n", __func__, __LINE__);
	system(
			"echo 0xc0  > /sys/kernel/config/usb_gadget/g1/configs/b.1/bmAttributes");
	if (access("/sys/kernel/config/usb_gadget/g1/configs/b.1/strings/0x409",
			F_OK)) {
		system(
				"mkdir /sys/kernel/config/usb_gadget/g1/configs/b.1/strings/0x409");
	}
	system(
			"echo \"PTP\"  > /sys/kernel/config/usb_gadget/g1/configs/b.1/strings/0x409/configuration");
	result = readlink(
			"/sys/kernel/config/usb_gadget/g1/configs/b.1/ptp_sd.usb0", path,
			1024 - 1);
	if (result < 0 || (result >= 1024 - 1)) {
		system(
				"ln -s /sys/kernel/config/usb_gadget/g1/functions/ptp_sd.usb0 /sys/kernel/config/usb_gadget/g1/configs/b.1");
	}

	DBGPRINT("%s:%d\n", __func__, __LINE__);
	if (access("/sys/kernel/config/usb_gadget/g1/configs/b.2", F_OK)) {
		system("mkdir /sys/kernel/config/usb_gadget/g1/configs/b.2");
	}
	system(
			"echo 0xc0  > /sys/kernel/config/usb_gadget/g1/configs/b.2/bmAttributes");
	if (access("/sys/kernel/config/usb_gadget/g1/configs/b.2/strings/0x409",
			F_OK)) {
		system(
				"mkdir /sys/kernel/config/usb_gadget/g1/configs/b.2/strings/0x409");
	}
	system(
			"echo \"iPod USB Interface\"  > /sys/kernel/config/usb_gadget/g1/configs/b.2/strings/0x409/configuration");
	result = readlink(
			"/sys/kernel/config/usb_gadget/g1/configs/b.2/audio_sd.usb0", path,
			1024 - 1);
	if (result < 0 || (result >= 1024 - 1)) {
		system(
				"ln -s /sys/kernel/config/usb_gadget/g1/functions/audio_sd.usb0 /sys/kernel/config/usb_gadget/g1/configs/b.2");
	}
	result = readlink(
			"/sys/kernel/config/usb_gadget/g1/configs/b.2/hid_sd.usb0", path,
			1024 - 1);
	if (result < 0 || (result >= 1024 - 1)) {
		system(
				"ln -s /sys/kernel/config/usb_gadget/g1/functions/hid_sd.usb0 /sys/kernel/config/usb_gadget/g1/configs/b.2");
	}

	DBGPRINT("%s:%d\n", __func__, __LINE__);
	if (access("/sys/kernel/config/usb_gadget/g1/configs/b.3", F_OK)) {
		system("mkdir /sys/kernel/config/usb_gadget/g1/configs/b.3");
	}
	system(
			"echo 0xc0  > /sys/kernel/config/usb_gadget/g1/configs/b.3/bmAttributes");
	if (access("/sys/kernel/config/usb_gadget/g1/configs/b.3/strings/0x409",
			F_OK)) {
		system(
				"mkdir /sys/kernel/config/usb_gadget/g1/configs/b.3/strings/0x409");
	}
	system(
			"echo \"PTP + Apple Mobile Device\"  > /sys/kernel/config/usb_gadget/g1/configs/b.3/strings/0x409/configuration");
	result = readlink(
			"/sys/kernel/config/usb_gadget/g1/configs/b.3/ptp_sd.usb0", path,
			1024 - 1);
	if (result < 0 || (result >= 1024 - 1)) {
		system(
				"ln -s /sys/kernel/config/usb_gadget/g1/functions/ptp_sd.usb0 /sys/kernel/config/usb_gadget/g1/configs/b.3");
	}
	result = readlink(
			"/sys/kernel/config/usb_gadget/g1/configs/b.3/mux_sd.usb0", path,
			1024 - 1);
	if (result < 0 || (result >= 1024 - 1)) {
		system(
				"ln -s /sys/kernel/config/usb_gadget/g1/functions/mux_sd.usb0 /sys/kernel/config/usb_gadget/g1/configs/b.3");
	}

	DBGPRINT("%s:%d\n", __func__, __LINE__);
	if (access("/sys/kernel/config/usb_gadget/g1/configs/b.4", F_OK)) {
		system("mkdir /sys/kernel/config/usb_gadget/g1/configs/b.4");
	}
	system(
			"echo 0xc0  > /sys/kernel/config/usb_gadget/g1/configs/b.4/bmAttributes");
	if (access("/sys/kernel/config/usb_gadget/g1/configs/b.4/strings/0x409",
			F_OK)) {
		system(
				"mkdir /sys/kernel/config/usb_gadget/g1/configs/b.4/strings/0x409");
	}

	DBGPRINT("%s:%d\n", __func__, __LINE__);
	system(
			"echo \"PTP + Apple Mobile Device + Apple USB Ethernet\"  > /sys/kernel/config/usb_gadget/g1/configs/b.4/strings/0x409/configuration");
	result = readlink(
			"/sys/kernel/config/usb_gadget/g1/configs/b.4/ptp_sd.usb0", path,
			1024 - 1);
	if (result < 0 || (result >= 1024 - 1)) {
		system(
				"ln -s /sys/kernel/config/usb_gadget/g1/functions/ptp_sd.usb0 /sys/kernel/config/usb_gadget/g1/configs/b.4");
	}
	DBGPRINT("%s:%d\n", __func__, __LINE__);
	result = readlink(
			"/sys/kernel/config/usb_gadget/g1/configs/b.4/mux_sd.usb0", path,
			1024 - 1);
	if (result < 0 || (result >= 1024 - 1)) {
		system(
				"ln -s /sys/kernel/config/usb_gadget/g1/functions/mux_sd.usb0 /sys/kernel/config/usb_gadget/g1/configs/b.4");
	}

	DBGPRINT("%s:%d\n", __func__, __LINE__);
	result = readlink(
			"/sys/kernel/config/usb_gadget/g1/configs/b.4/vsc_sd.usb0", path,
			1024 - 1);
	if (result < 0 || (result >= 1024 - 1)) {
		system(
				"ln -s /sys/kernel/config/usb_gadget/g1/functions/vsc_sd.usb0 /sys/kernel/config/usb_gadget/g1/configs/b.4");
	}

	DBGPRINT("%s:%d\n", __func__, __LINE__);
	if (strlen(g_usb_udc_path) <= 1) {
		g_find_udc_path = 1;
		__system_property_get("sys.usb.controller", g_usb_udc_path);
	}

	DBGPRINT("g_usb_udc_path:%s\n", g_usb_udc_path);
	if (g_find_udc_path > 0 && strlen(g_usb_udc_path) > 1){
		char echo_path[1024] = { 0 };
		strcpy(echo_path, "echo ");
		strcat(echo_path, g_usb_udc_path);
		strcat(echo_path, " > ");
		strcat(echo_path, "/config/usb_gadget/g1/UDC");
		DBGPRINT("echo_path:%s\n", echo_path);
		system(echo_path); //system("echo ff300000.usb > /config/usb_gadget/g1/UDC");
	}

	DBGPRINT("%s:%d end\n", __func__, __LINE__);
	return ret;
}

int platfrom_usb_switch_init() {
	DBGPRINT("%s:%d\n", __func__, __LINE__);

	__system_property_get("ro.board.platform", board_platform);
	DBGPRINT("board_platform %s %s:%d\n", board_platform, __func__, __LINE__);

	check_usb_usb_gadget_UDC();
	check_platform_otg_path();

	if (g_find_otg_path == 0)
		return 0;

	if (strcmp(custom_id, "sd_msm808") == 0) {
		DBGPRINT("echo 38 > /sys/class/gpio/export\n");
		system("echo 38 > /sys/class/gpio/export");

		DBGPRINT("echo out > /sys/class/gpio/gpio38/direction\n");
		system("echo out > /sys/class/gpio/gpio38/direction");

		DBGPRINT("echo 1 > /sys/class/gpio/gpio38/value\n");
		system("echo 1 > /sys/class/gpio/gpio38/value");

		DBGPRINT("echo 63 > /sys/class/gpio/export\n");
		system("echo 63 > /sys/class/gpio/export");

		DBGPRINT("echo out > /sys/class/gpio/gpio63/direction\n");
		system("echo out > /sys/class/gpio/gpio63/direction");

		DBGPRINT("echo 1 > /sys/class/gpio/gpio63/value\n");
		system("echo 1 > /sys/class/gpio/gpio63/value");
	}

	if (strlen(g_otg_path) > 0) {
		char value[256] = { 0 };
		int i, size, fd, ret = -1;

		if ((fd = open(g_otg_path, O_RDONLY)) < 0) {
			DBGPRINT(
					"open(%s) failed: %s (%d)\n", g_otg_path, strerror(errno), errno);
			return 0;
		}
		memset(value, 0, sizeof(value));
		size = read(fd, &value, sizeof(value));
		DBGPRINT("value=%s,%s:%d\n", value, __func__, __LINE__);
		close(fd);
		platform_usb_apple_device();
	}
	return 1;
}

int platfrom_usb_switch_device() {
	DBGPRINT("%s:%d\n", __func__, __LINE__);

	if (g_find_otg_path == 0)
		return 0;

	if (strcmp(custom_id, "sd_msm808") == 0) {
		DBGPRINT("echo 1 > /sys/class/gpio/gpio63/value\n");
		system("echo 1 > /sys/class/gpio/gpio63/value");
		if (strlen(g_otg_path) > 0) {
			char echo_path[1024] = { 0 };
			strcpy(echo_path, "echo \"peripheral\" > ");
			strcat(echo_path, g_otg_path);
			DBGPRINT("echo_path:%s\n", echo_path);
			system(echo_path); //1 host; 2 device
		}
		return 1;
	}

	if (strlen(g_otg_path) > 0) {
		char echo_path[1024] = { 0 };
		strcpy(echo_path, "echo \"2\" > ");
		strcat(echo_path, g_otg_path);
		DBGPRINT("echo_path:%s\n", echo_path);
		system(echo_path); //1 host; 2 device
	}
	return 1;
}

void platfrom_usb_switch_host() {
	DBGPRINT("%s:%d\n", __func__, __LINE__);

	if (g_find_otg_path == 0)
		return;

	if (strcmp(custom_id, "sd_msm808") == 0) {
		DBGPRINT("echo 0 > /sys/class/gpio/gpio63/value\n");
		system("echo 0 > /sys/class/gpio/gpio63/value");
	}

	if (strlen(g_otg_path) > 0) {
		char value[256] = { 0 };
		int i, size, fd, ret = -1;

		if ((fd = open(g_otg_path, O_RDONLY)) < 0) {
			DBGPRINT(
					"open(%s) failed: %s (%d)\n", g_otg_path, strerror(errno), errno);
			return;
		}
		memset(value, 0, sizeof(value));
		size = read(fd, &value, sizeof(value));
		DBGPRINT("value=%s,%s:%d\n", value, __func__, __LINE__);
		close(fd);
		if ((!strncmp(value, "2", 1) || !strncmp(value, "peripheral", 10)
				|| !strncmp(value, "usb_device", 10))) {
			char echo_path[1024] = { 0 };
			if (strcmp(custom_id, "sd_msm808") == 0) {
				{
					strcpy(echo_path, "echo \"host\" > ");
				}
			} else {
				strcpy(echo_path, "echo \"1\" > ");
			}
			strcat(echo_path, g_otg_path);
			DBGPRINT("echo_path:%s\n", echo_path);
			system(echo_path); //1 host; 2 device
			DBGPRINT("echo_path:%s end\n", echo_path);
			if ((fd = open(g_otg_path, O_RDONLY)) < 0) {
				DBGPRINT(
						"open(%s) failed: %s (%d)\n", g_otg_path, strerror(errno), errno);
				return;
			}

			memset(value, 0, sizeof(value));
			size = read(fd, &value, sizeof(value));
			DBGPRINT("return value=%s,%s:%d\n", value, __func__, __LINE__);
			close(fd);
		}
	}

	DBGPRINT("%s:%d\n", __func__, __LINE__);
}

#if 0
void main()
{
	platfrom_usb_switch_init();
}
#endif
